package geneticpolyimage;

import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 * Class Problem to represent the problem in memeory
 * 
 * @author igor & mattia
 */
public class Problem {
    public BufferedImage targetimage = null;
    public boolean done = false;
    int width = 0;
    int height = 0;
    private int[] targetPixels;

    Problem(String filename) throws Exception {
        loadImage(filename);
    }

    /**
     * Load image to try to represent
     * @param ref path of image to load
     * @throws Exception
     */
    public void loadImage(String ref) throws Exception {
        BufferedImage bimg = null;
            bimg = ImageIO.read(new File(ref));
            width = bimg.getWidth();
            height = bimg.getHeight();
            targetimage = bimg;
            done = true;

            targetPixels = new int[bimg.getWidth() * bimg.getHeight()];
            PixelGrabber pg = new PixelGrabber(bimg, 0, 0, bimg.getWidth(),
                    bimg.getHeight(), targetPixels, 0, bimg.getWidth());
            pg.grabPixels();
    }

    /**
     * Compare generated image vs target image
     * @param ind individual to check
     * @return distance between image
     */
    double verify(Individual ind) {
        BufferedImage imagetotest = ind.getImage();

        //calculate distance between given image
        final int[] generatedPixels = new int[imagetotest.getWidth() * imagetotest.getHeight()];
        PixelGrabber pg = new PixelGrabber(imagetotest, 0, 0, imagetotest.getWidth(),
                imagetotest.getHeight(), generatedPixels, 0, imagetotest.getWidth());
        try {
            pg.grabPixels();
        } catch (InterruptedException ex) {
            Logger.getLogger(Problem.class.getName()).log(Level.SEVERE, null, ex);
        }

        
        double sum = 0;
        for (int i = 0; i < generatedPixels.length && i < targetPixels.length; i++) {
            int c1 = targetPixels[i];
            int c2 = generatedPixels[i];

            int r = ((c1 >> 16) & 0xff) - ((c2 >> 16) & 0xff);
            int g = ((c1 >> 8) & 0xff) - ((c2 >> 8) & 0xff);
            int b = (c1 & 0xff) - (c2 & 0xff);

            sum += Math.sqrt(r * r + g * g + b * b);
        }
        return  (1 - sum / (Math.sqrt(255 * 255 * 3) * (double) generatedPixels.length));
    }

    /**
     * Calculate difference image between target image and best individual image
     * @param ind individual to compare to target image
     * @return difference image
     */
    BufferedImage diffimage(Individual ind) {
        BufferedImage imagetotest = ind.getImage();
        //calculate distance between given image
        final int[] generatedPixels = new int[imagetotest.getWidth() * imagetotest.getHeight()];
        PixelGrabber pg = new PixelGrabber(imagetotest, 0, 0, imagetotest.getWidth(),
                imagetotest.getHeight(), generatedPixels, 0, imagetotest.getWidth());
        try {
            pg.grabPixels();
        } catch (InterruptedException ex) {
            Logger.getLogger(Problem.class.getName()).log(Level.SEVERE, null, ex);
        }

        int[] diff = new int[targetPixels.length];
        
        for (int i = 0; i < generatedPixels.length && i < targetPixels.length; i++) {
            int c1 = targetPixels[i];
            int c2 = generatedPixels[i];

            int r = ((c1 >> 16) & 0xff) - ((c2 >> 16) & 0xff);
            int g = ((c1 >> 8) & 0xff) - ((c2 >> 8) & 0xff);
            int b = (c1 & 0xff) - (c2 & 0xff);

            diff[i]= (((int) (Math.sqrt(r * r + g * g + b * b)*255/Math.sqrt(255*255*3)))<<24);
        }

        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        bi.setRGB(0, 0, width, height, diff, 0, width);
        return bi;

    }
}
